package com.authine.cloudpivot.ext.applicationservice;

import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.Assert;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.data.condition.Order;
import com.authine.cloudpivot.data.support.OrderImpl;
import com.authine.cloudpivot.data.support.SortableImpl;
import com.authine.cloudpivot.ext.conf.ApplicationConf;
import com.authine.cloudpivot.ext.domain.bo.MarketGoodsBo;
import com.authine.cloudpivot.ext.domain.dto.*;
import com.authine.cloudpivot.ext.domain.impl.CreateOrderTransactionCallbackImpl;
import com.authine.cloudpivot.ext.domain.impl.MailTask;
import com.authine.cloudpivot.ext.domain.vo.*;
import com.authine.cloudpivot.ext.enums.*;
import com.authine.cloudpivot.ext.util.*;
import com.authine.common.util.IdWorker;
import com.authine.hermes.app.launcher.service.ApplicationService;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.query.ListBOQuery;
import com.authine.mvp.app.launcher.dto.bo.query.expression.*;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.launcher.gateway.bo.BOValidatedAndFormatService;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.http.HttpMethod;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.authine.cloudpivot.ext.conf.ApplicationConf.*;
import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

/**
 * @program: gm-market
 * @description: 固买市场
 * @author: wlw
 * @create: 2021-08-09 16:36
 **/
@Path("MarketGoodsMallService")
@Slf4j
public class MarketGoodsMallService extends ApplicationService {
    private JdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(JdbcTemplate.class);
    private BOValidatedAndFormatService boValidatedAndFormatService = ApplicationContextUtils.getBean(BOValidatedAndFormatService.class);
    private TransactionTemplate transactionTemplate = ApplicationContextUtils.getBean(TransactionTemplate.class);
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private final String CREATE_ORDER = "createOrder";

    @POST
    @Path("multistage")
    @Operation(summary = "固买市场-商品分类", tags = CUSTOM_SERVICE)
    public SingleResponse<List<CatalogVo>> multistage(){
        SingleResponse<BOList> singleResponse = BoServiceUtils.findListBySimple(ApplicationConf.CATALOG, "deleted", 0, Operator.EQ);
        Assert.isTrue(singleResponse.isSuccess()&&!CollectionUtils.isEmpty(singleResponse.getData().getData()),"无商品目录数据");
        List<Map<String, Object>> data = singleResponse.getData().getData();
        List<CatalogVo> catalogVos = data.stream().map(t -> CatalogVo.builder().id((String)t.get("id")).name((String)t.get("name")).parentId((String)t.get("parent_id")).value((String)t.get("id")).build()).collect(Collectors.toList());
        catalogVos.forEach(v-> v.setChildren(catalogVos.stream().filter(f->v.getId().equals(f.getParentId())).collect(Collectors.toList())));
        return SingleResponse.of(catalogVos.stream().filter(f->StringUtils.isEmpty(f.getParentId())).collect(Collectors.toList()));
    }



    @POST
    @Path("shopPage")
    @Operation(summary = "固买市场-市场商品分页查询", tags = CUSTOM_SERVICE)
    public SingleResponse<ShopPageVo> shopPage(@Parameter ShopPageQuery shopPageQuery){
        Assert.isTrue(Objects.nonNull(shopPageQuery),"参数不能为空");
        ShopPageVo shopPageVo = ShopPageVo.builder().build();
        //条件分页查询
        executeFullQuery(shopPageQuery,shopPageVo);
        //sku分页查询
        executeGoodsQuery(shopPageQuery,shopPageVo);
        return  SingleResponse.of(shopPageVo);

    }

    @POST
    @Path("updateCartNum")
    @Operation(summary = "固买市场-更新购物车", tags = CUSTOM_SERVICE)
    public SingleResponse updateCartNum(@Parameter UpdateCartNumDto updateCartNumDto){
        Assert.isTrue(Objects.nonNull(updateCartNumDto), "参数不能为空");
        Assert.isTrue(!StringUtils.isEmpty(updateCartNumDto.getId()), "购物车id不能为空");
        Assert.isTrue(!StringUtils.isEmpty(updateCartNumDto.getGoods_number()), "商品数量不能为空");
        Assert.isTrue(0 <= updateCartNumDto.getGoods_number() || 99999999 >= updateCartNumDto.getGoods_number(), "商品数量有误");
        BO cartBo = BoServiceUtils.loadByBizObjectId(SHOPPING_CAR, updateCartNumDto.getId()).getData();
        if(Objects.isNull(cartBo)||Objects.isNull(cartBo.getData())){
            throw new BizException("购物车数据不存在");
        }
        BO goodsBo = BoServiceUtils.loadByBizObjectId(GOODES, (String) cartBo.getData().get("goods_id")).getData();
        if(Objects.isNull(goodsBo)||Objects.isNull(goodsBo.getData())){
            throw new BizException("商品数据不存在");
        }
        MarketGoodsVo goods = BoUtils.Map2Bo(goodsBo.getData(), MarketGoodsVo.class);
        //商品常规校验
        goodsCommonCheck(goods);
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("id",updateCartNumDto.getId());
        paramMap.put("quantity",updateCartNumDto.getGoods_number());
        return BoServiceUtils.updateBo(SHOPPING_CAR,paramMap);
    }


    @POST
    @Path("addCart")
    @Operation(summary = "固买市场-添加购物车/立即购买", tags = CUSTOM_SERVICE)
    public SingleResponse<List<CartGoodsVo>> addCart(@Parameter AddCartDto addCartDto){
        Assert.isTrue(Objects.nonNull(addCartDto), "参数不能为空");
        Assert.isTrue(!StringUtils.isEmpty(addCartDto.getGoods_id()), "商品id不能为空");
        Assert.isTrue(!StringUtils.isEmpty(addCartDto.getGoods_number()), "商品数量不能为空");
        Assert.isTrue(!PmUtil.isPm(),"平台不可操作");
        Assert.isTrue(0 <= addCartDto.getGoods_number() || 99999999 >= addCartDto.getGoods_number(), "商品数量有误");
        BO bo = BoServiceUtils.loadByBizObjectId(ApplicationConf.GOODES, addCartDto.getGoods_id()).getData();
        Assert.isTrue(Objects.nonNull(bo) && Objects.nonNull(bo.getData()) && 0 == (Integer) bo.getData().get("deleted"), "此商品不存在");
        MarketGoodsVo goods = BoUtils.Map2Bo(bo.getData(), MarketGoodsVo.class);
        //商品常规校验
        goodsCommonCheck(goods);
        BigDecimal stock = (BigDecimal) bo.getData().get("stock");
        Assert.isTrue(new BigDecimal(addCartDto.getGoods_number()).compareTo(stock) <= 0, "库存不足");

       //数据预备
        Map<String, Object> cart = initCart(goods, addCartDto);
        Map<String, BigDecimal> skuPriceMap = PmUtil.calculateSkuPrice(goods);
        CartGoodsVo.CartGoodsVoBuilder builder = CartGoodsVo.builder()
                .pretax_price((BigDecimal) cart.get("pretax_price"))
                .goods_id((String) cart.get("goods_id"))
                .price(skuPriceMap.get("showPrice"))
                .total_amount(skuPriceMap.get("showPretaxPrice"))
                .marketGoodsVo(goods);


        if (!addCartDto.getFlag()) {
            JSONObject map = JSON.parseObject(JSON.toJSONString(addCartDto));
            //立即购买添加的购物车为不启用
            map.put("enabled", false);
            BoServiceUtils.createBo(ApplicationConf.SHOPPING_CAR, cart);
            return SingleResponse.of(Collections.singletonList(builder
                    .id(((Long) cart.get("id")).toString())
                    .build()));
        }

        //构造查询
        SimpleCondition goods_id = new SimpleCondition("goods_id", Operator.EQ, addCartDto.getGoods_id());
        SimpleCondition enabled = new SimpleCondition("enabled", Operator.EQ, 1);
        SimpleCondition del = new SimpleCondition("deleted", Operator.EQ, 0);
        SimpleCondition owner = new SimpleCondition("owner", Operator.EQ, RequestContext.getCorpLoginId());
        ComplexCondition complexCondition = new ComplexCondition();
        complexCondition.setNature(Nature.AND);
        complexCondition.setConditions(Arrays.asList(goods_id, enabled, del, owner));
        BOList data = BoServiceUtils.findListByCondition(ApplicationConf.SHOPPING_CAR, complexCondition).getData();
        //新增或更新购物车
        if (Objects.nonNull(data) && !CollectionUtils.isEmpty(data.getData())) {
            Map<String, Object> map = CollectionUtils.firstElement(data.getData());
            BigDecimal currentNum = (BigDecimal) map.get("quantity");
            BigDecimal addAfter = currentNum.add(new BigDecimal(addCartDto.getGoods_number()));
            Assert.isTrue(addAfter.compareTo(stock) < 0, "库存不足,可添加数量为" + stock.subtract(currentNum).doubleValue());
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("id", map.get("id"));
            paramMap.put("quantity", addAfter);
            BoServiceUtils.updateBo(ApplicationConf.SHOPPING_CAR, paramMap);
            return SingleResponse.of(Collections.singletonList(builder
                    .id((String)map.get("id"))
                    .build()));
        }else {
            BoServiceUtils.createBo(ApplicationConf.SHOPPING_CAR, initCart(goods, addCartDto));
            return SingleResponse.of(Collections.singletonList(builder
                    .id(((Long) cart.get("id")).toString())
                    .build()));
        }
    }

    private void goodsCommonCheck(MarketGoodsVo bo) {
        Assert.isTrue(bo.getSaled(), "商品已下架");
        Assert.isTrue(bo.getEnabled() ,"商品已不可采购");
        Assert.isTrue((bo.getExpiry()).getTime() > System.currentTimeMillis(), "商品已过期");
    }

    @POST
    @Path("cartSum")
    @Operation(summary = "固买市场-购物车数量", tags = CUSTOM_SERVICE)
    public SingleResponse<Integer> cartSum(){
        String loginId = RequestContext.getCorpLoginId();
        Assert.isTrue(!StringUtils.isEmpty(loginId),"请登录后查看");
        BOList data = getCartBoList(loginId);
        return SingleResponse.of(Optional.of(data.getTotal()).orElse(0));
    }

    @POST
    @Path("cartList")
    @Operation(summary = "固买市场-购物车列表", tags = CUSTOM_SERVICE)
    public SingleResponse<List<CartGoodsVo>> cartList(){
        String loginId = RequestContext.getCorpLoginId();
        Assert.isTrue(!StringUtils.isEmpty(loginId),"请登录后查看");
        BOList data = getCartBoList(loginId);
        if(CollectionUtils.isEmpty(data.getData())) return SingleResponse.of(Lists.newArrayList());
        return SingleResponse.of(data.getData().stream().map(v->{
            CartGoodsVo goodsVo = CartGoodsVo.builder()
                    .id((String) v.get("id"))
                    .goods_id((String) v.get("goods_id"))
                    .goods_number((BigDecimal) v.get("quantity"))
                    .marketGoodsVo(BoUtils.Map2Bo(BoServiceUtils.loadByBizObjectId(ApplicationConf.GOODES, (String) v.get("goods_id")).getData().getData(), MarketGoodsVo.class))
                    .build();
            Map<String, BigDecimal> calculateSkuPrice = PmUtil.calculateSkuPrice(goodsVo.getMarketGoodsVo());
            goodsVo.setPretax_price(calculateSkuPrice.get("showPretaxPrice"));
            goodsVo.setPrice(calculateSkuPrice.get("showPrice"));
            goodsVo.setTotal_amount(goodsVo.getPrice().multiply(goodsVo.getGoods_number()));
            return goodsVo;
        }).collect(Collectors.toList()));
    }

    @POST
    @Path("loadGoodsDetail")
    @Operation(summary = "固买市场-获取商品详情", tags = CUSTOM_SERVICE)
    public SingleResponse<MarketGoodsVo> loadGoodsDetail(@Parameter LoadGoodsDetailDto loadGoodsDetailDto){
        Assert.isTrue(!StringUtils.isEmpty(loadGoodsDetailDto),"参数不能为空");
        Assert.isTrue(!StringUtils.isEmpty(loadGoodsDetailDto.getGoodsId()),"参数不能为空");
        SingleResponse<BO> response = BoServiceUtils.loadByBizObjectId(GOODES, loadGoodsDetailDto.getGoodsId());
        if(!response.isSuccess()||Objects.isNull(response.getData().getData())){
            throw new BizException("商品信息不存在");
        }
        MarketGoodsVo goodsVo = BoUtils.Map2Bo(response.getData().getData(), MarketGoodsVo.class);
        Map<String, BigDecimal> calculateSkuPrice = PmUtil.calculateSkuPrice(goodsVo);
        goodsVo.setPretax_price(calculateSkuPrice.get("showPretaxPrice"));
        goodsVo.setPrice(calculateSkuPrice.get("showPrice"));
        return SingleResponse.of(goodsVo);

    }

    @POST
    @Path("createOrder")
    @Operation(summary = "固买市场-提交订单", tags = CUSTOM_SERVICE)
    public SingleResponse createOrder(@Parameter CreateOrderDto createOrderDto){
        String requestId = UUID.randomUUID().toString();
        try {
            Assert.isTrue(!StringUtils.isEmpty(createOrderDto),"参数不能为空");
            Assert.isTrue(!PmUtil.isPm(),"平台不能下单");
            Boolean aBoolean = RedisUtil.lock(RequestContext.getCorpLoginId() + CREATE_ORDER, 300,500, requestId);
            Assert.isTrue(aBoolean,"订单处理中，请稍后重试");
            //加锁成功，更新购物车状态
            List<Map<String, Object>> maps = createOrderDto.getCartIds().stream().map(v -> {
                Map<String, Object> map = Maps.newHashMap();
                map.put("id", v.getId());
                map.put("enabled", false);
                return map;
            }).collect(Collectors.toList());
            BoServiceUtils.batchUpdateBo(SHOPPING_CAR,maps);
            Map<String, GoodsMaterialDto> materialDtoMap = createOrderDto.getCartIds().stream().collect(Collectors.toMap(GoodsMaterialDto::getGoods_id, v -> v));
            SingleResponse<BOList> singleResponse = BoServiceUtils.findListBySimple(ApplicationConf.SHOPPING_CAR, "id", createOrderDto.getCartIds().stream().map(GoodsMaterialDto::getId).collect(Collectors.toList()), Operator.IN);
            Assert.isTrue(singleResponse.isSuccess()&&!CollectionUtils.isEmpty(singleResponse.getData().getData()),"购物车数据不存在");
            //供应商id分组
            Map<String, List<GoodsMaterialDto>> vendorGoodsMaterialDtoMap = createOrderDto.getCartIds().stream().collect(Collectors.groupingBy(GoodsMaterialDto::getVendor_id));

            //初始化客户订单
            Map<String, Object> customerOrder = initCustomerOrder(createOrderDto);
            List<Map<String, Object>> supplierOrderList = Lists.newArrayList();
            List<Map<String, Object>> supplierOrderGoodsList = Lists.newArrayList();
            List<Map<String, Object>> customerOrderGoodsList = Lists.newArrayList();

            /**----------------------------------初始化订单----------------------------------------- **/
            buildOrder(1,createOrderDto, materialDtoMap, vendorGoodsMaterialDtoMap, customerOrder, supplierOrderList, supplierOrderGoodsList, customerOrderGoodsList);
            //执行器
            transactionTemplate.execute(new CreateOrderTransactionCallbackImpl(supplierOrderList,supplierOrderGoodsList,customerOrderGoodsList,customerOrder));
            return SingleResponse.buildSuccess();
        } finally {
            Boolean aBoolean = RedisUtil.unlock(RequestContext.getCorpLoginId() + CREATE_ORDER, requestId);
            if (!aBoolean){
                log.warn("【createOrder】 解锁失败 key：{}",RequestContext.getCorpLoginId() + CREATE_ORDER);
            }
        }
    }


    @POST
    @Path("lookedAndLooked")
    @Operation(summary = "固买市场-看了又看", tags = CUSTOM_SERVICE)
    public SingleResponse<List<MarketGoodsVo>> lookedAndLooked(@Parameter LookedAndLookedDto lookedAndLookedDto){
        Assert.isTrue(Objects.nonNull(lookedAndLookedDto),"参数不能为空");
        Assert.isTrue(!StringUtils.isEmpty(lookedAndLookedDto.getCatalog()),"目录不能为空");
        ComplexCondition condition = new ComplexCondition();
        condition.setNature(Nature.AND);
        condition.getConditions().add(new SimpleCondition("deleted",Operator.EQ,0));
        condition.getConditions().add(new SimpleCondition("enabled",Operator.EQ,1));
        condition.getConditions().add(new SimpleCondition("saled",Operator.EQ,1));
        condition.getConditions().add(new SimpleCondition("catalog",Operator.EQ,lookedAndLookedDto.getCatalog()));
        SingleResponse<BOList> response = BoServiceUtils.findListByConditionPageSize(ApplicationConf.GOODES, condition,3);
        return SingleResponse.of(response.getData().getData().stream().map(l->{
            MarketGoodsVo goodsVo = BoUtils.Map2Bo(l, MarketGoodsVo.class);
            Map<String, BigDecimal> map = PmUtil.calculateSkuPrice(goodsVo);
            goodsVo.setPretax_price(map.get("showPretaxPrice"));
            goodsVo.setPrice(map.get("showPrice"));
            return goodsVo;
        }).collect(Collectors.toList()));
    }

    @POST
    @Path("refund")
    @Operation(summary = "固买市场-申请退款", tags = CUSTOM_SERVICE)
    public SingleResponse refund(@Parameter RefundDto refundDto){
        Assert.isTrue(Objects.nonNull(refundDto),"参数不能为空");
        String url = PmUtil.getUrl(orderCenter);
        Assert.isTrue(!StringUtils.isEmpty(url),"服务地址获取失败");
        String fullUrl =url.concat(customerApplyRefund);
        Map singleResponse = RestTemplateUtil.restArray(fullUrl, Collections.singletonList(refundDto), HttpMethod.POST);
        log.info("[refund] 响应：{}",JSON.toJSONString(singleResponse));
        SingleResponse response = BoUtils.Map2Bo(singleResponse, SingleResponse.class);
        Assert.isTrue(response.isSuccess(),response.getErrMessage());
        return response;
    }










//-----------------------------------------------------分割线-----------------------------------------------------------------//






    private BOList getCartBoList(String loginId) {
        SimpleCondition enabled = new SimpleCondition("enabled", Operator.EQ, 1);
        SimpleCondition del = new SimpleCondition("deleted", Operator.EQ, 0);
        SimpleCondition owner = new SimpleCondition("owner", Operator.EQ, loginId);
        SimpleCondition type = new SimpleCondition("type", Operator.EQ, CartTypeEnum.SHOP.getId());
        ComplexCondition complexCondition = new ComplexCondition();
        complexCondition.setNature(Nature.AND);
        complexCondition.setConditions(Arrays.asList(owner,enabled,del));
        return BoServiceUtils.findListByCondition(ApplicationConf.SHOPPING_CAR, complexCondition).getData();
    }

    private void executeFullQuery(ShopPageQuery shopPageQuery,ShopPageVo shopPageVo){
        int index = shopPageQuery.getAttrPage()*shopPageQuery.getAttrLimit();
        StringBuilder sql = new StringBuilder("select ");
        if(Objects.isNull(shopPageQuery.getAttrType())){
            sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct brand),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as brands,");
            sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct model),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as models,");
            sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct spec),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as specs, ");
            sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct name),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as names ");

        }else {
            if (1 ==shopPageQuery.getAttrType())
                sql.append("distinct brand as brands ");
                //sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct brand),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as brands ");
            if (2 == shopPageQuery.getAttrType())
                sql.append("distinct model as models ");
                //sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct model),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as models ");
            if (3 == shopPageQuery.getAttrType())
                sql.append("distinct spec as specs ");
            //sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct spec),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as specs ");
            if (4 == shopPageQuery.getAttrType())
                sql.append("distinct name as names ");
            //sql.append("SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(distinct name),',',").append(index).append("),',',").append(-shopPageQuery.getAttrLimit()).append(") as names ");
        }
        sql.append("from ").append("(select brand,model,spec,name from ").append(COMMODITYMATERIALS_GOODES).append(" where review_status = 3 and saled = 1 and enabled = 1 and deleted = 0 and mall_goods_type = 1 ");
        if(!CollectionUtils.isEmpty(shopPageQuery.getBrands()))
            sql.append("and brand in ").append("(").append(String.join(",", PmUtil.listFormatSqlString(shopPageQuery.getBrands()))).append(") ");
        if(!CollectionUtils.isEmpty(shopPageQuery.getModels()))
            sql.append("and model in ").append("(").append(String.join(",", PmUtil.listFormatSqlString(shopPageQuery.getModels()))).append(") ");
        if(!CollectionUtils.isEmpty(shopPageQuery.getSpecs()))
            sql.append("and spec in ").append("(").append(String.join(",", PmUtil.listFormatSqlString(shopPageQuery.getSpecs()))).append(") ");
        if(!StringUtils.isEmpty(shopPageQuery.getMallFeatured()))
            sql.append("and mall_featured = ").append("\"").append(shopPageQuery.getMallFeatured()).append("\"");
        if(!StringUtils.isEmpty(shopPageQuery.getCatalog()))
            sql.append("and catalog = ").append("\"").append(shopPageQuery.getCatalog()).append("\"");
        if(!StringUtils.isEmpty(shopPageQuery.getKeyword())){
            sql.append("and (brand like concat('%','").append(shopPageQuery.getKeyword()).append("','%') ");
            sql.append("or model like concat('%','").append(shopPageQuery.getKeyword()).append("','%') ");
            sql.append("or name like concat('%','").append(shopPageQuery.getKeyword()).append("','%')) ");
        }
        sql.append(" limit 30000) temp");
        if(Objects.nonNull(shopPageQuery.getAttrType())){
            sql.append(" limit ").append((shopPageQuery.getAttrPage()-1)*shopPageQuery.getAttrLimit()).append(",").append(shopPageQuery.getAttrLimit());
            log.info("query查询sql===》"+sql.toString());
            List<String> list = jdbcTemplate.queryForList(sql.toString(), String.class);
            shopPageVo.setBrand(1 == shopPageQuery.getAttrType()?list:Lists.newArrayList());
            shopPageVo.setModel(2 == shopPageQuery.getAttrType()?list:Lists.newArrayList());
            shopPageVo.setSpec(3 == shopPageQuery.getAttrType()?list:Lists.newArrayList());
            shopPageVo.setNames(4 == shopPageQuery.getAttrType()?list:Lists.newArrayList());
        }else {
            log.info("query查询sql===》" + sql.toString());
            ShopPageVo pageVo = jdbcTemplate.queryForObject(sql.toString(), (rs, rowNum) ->
                    ShopPageVo.builder()
                            .brand((Arrays.asList(Optional.ofNullable(rs.getString("brands")).orElse("").split(","))))
                            .model((Arrays.asList(Optional.ofNullable(rs.getString("models")).orElse("").split(","))))
                            .spec((Arrays.asList(Optional.ofNullable(rs.getString("specs")).orElse("").split(","))))
                            .names((Arrays.asList(Optional.ofNullable(rs.getString("names")).orElse("").split(","))))
                            .build());
            if (Objects.nonNull(pageVo)) {
                shopPageVo.setBrand(Optional.ofNullable(pageVo.getBrand()).orElse(Lists.newArrayList()));
                shopPageVo.setModel(Optional.ofNullable(pageVo.getModel()).orElse(Lists.newArrayList()));
                shopPageVo.setSpec(Optional.ofNullable(pageVo.getSpec()).orElse(Lists.newArrayList()));
                shopPageVo.setNames(Optional.ofNullable(pageVo.getNames()).orElse(Lists.newArrayList()));

            }
        }
    }


    private void executeGoodsQuery(ShopPageQuery shopPageQuery,ShopPageVo shopPageVo){
        ListBOQuery boQuery = buildQuery(shopPageQuery);
        if(!StringUtils.isEmpty(shopPageQuery.getPageSize())) boQuery.setPageSize(shopPageQuery.getPageSize());
        if(!StringUtils.isEmpty(shopPageQuery.getPageIndex())) boQuery.setPageIndex(shopPageQuery.getPageIndex()-1);
        if(!StringUtils.isEmpty(shopPageQuery.getMallFeatured())) ((ComplexCondition)boQuery.getCondition()).getConditions().add(new SimpleCondition("mall_featured",Operator.EQ,shopPageQuery.getMallFeatured()));
        if(!StringUtils.isEmpty(shopPageQuery.getDeliveryPlace())) ((ComplexCondition)boQuery.getCondition()).getConditions().add(new SimpleCondition("delivery_place",Operator.EQ,shopPageQuery.getDeliveryPlace()));

        BOList data = BoServiceUtils.sortQuery(
                boQuery,
                Objects.isNull(shopPageQuery.getSortType())?null:
                0 == shopPageQuery.getSortType() ? new SortableImpl(Collections.singletonList(new OrderImpl("price", Order.Dir.ASC))) :
                        1 == shopPageQuery.getSortType() ? new SortableImpl(Collections.singletonList(new OrderImpl("price", Order.Dir.DESC))):null
                                ).getData();
        data.getData().forEach(l->{
            MarketGoodsVo goodsVo = BoUtils.Map2Bo(l, MarketGoodsVo.class);
            Map<String, BigDecimal> map = PmUtil.calculateSkuPrice(goodsVo);
            l.put("pretax_price",map.get("showPretaxPrice"));
            l.put("price",map.get("showPrice"));
        });
        if(!CollectionUtils.isEmpty(data.getData())){
            shopPageVo.setSku(JSON.parseArray(JSON.toJSONString(data.getData()),MarketGoodsVo.class));
        }else {
            shopPageVo.setSku(Lists.newArrayList());
        }
        shopPageVo.setCount(data.getTotal());
    }
    private ListBOQuery buildQuery(ShopPageQuery shopPageQuery ){
        ListBOQuery query = new ListBOQuery();
        query.setSchemaCode(ApplicationConf.GOODES);
        ComplexCondition condition = new ComplexCondition();
        if(!CollectionUtils.isEmpty(shopPageQuery.getBrands()))condition.getConditions().add(new SimpleCondition("brand",Operator.IN,shopPageQuery.getBrands()));
        if(!CollectionUtils.isEmpty(shopPageQuery.getModels()))condition.getConditions().add(new SimpleCondition("model",Operator.IN,shopPageQuery.getModels()));
        if(!CollectionUtils.isEmpty(shopPageQuery.getSpecs()))condition.getConditions().add(new SimpleCondition("spec",Operator.IN,shopPageQuery.getSpecs()));
        if(!StringUtils.isEmpty(shopPageQuery.getCatalog()))condition.getConditions().add(new SimpleCondition("catalog",Operator.EQ,shopPageQuery.getCatalog()));
        if(!StringUtils.isEmpty(shopPageQuery.getMallFeatured())) condition.getConditions().add(new SimpleCondition("mall_featured",Operator.IN,shopPageQuery.getMallFeatured()));
        if(!StringUtils.isEmpty(shopPageQuery.getKeyword())){
            ComplexCondition childComplexCondition = new ComplexCondition();
            childComplexCondition.setNature(Nature.OR);
            childComplexCondition.getConditions().add(new SimpleCondition("brand",Operator.LIKE,shopPageQuery.getKeyword()));
            childComplexCondition.getConditions().add(new SimpleCondition("model",Operator.LIKE,shopPageQuery.getKeyword()));
            childComplexCondition.getConditions().add(new SimpleCondition("spec",Operator.LIKE,shopPageQuery.getKeyword()));
            childComplexCondition.getConditions().add(new SimpleCondition("name",Operator.LIKE,shopPageQuery.getKeyword()));
            condition.getConditions().add(childComplexCondition);
        }
        condition.getConditions().add(new SimpleCondition("review_status",Operator.EQ, ApproveStatusEnum.APPROVE.getCode()));
        condition.getConditions().add(new SimpleCondition("enabled",Operator.EQ, 1));
        condition.getConditions().add(new SimpleCondition("saled",Operator.EQ, 1));
        condition.getConditions().add(new SimpleCondition("deleted",Operator.EQ, 0));
        condition.getConditions().add(new SimpleCondition("mall_goods_type",Operator.EQ, 1));
        condition.setNature(Nature.AND);
        query.setCondition(condition);
        return query;
    }

    //初始化客户订单
    private Map<String,Object> initCustomerOrder(CreateOrderDto createOrderDto){
        Map<String, Object> map = Maps.newHashMap();
        map.put("id",String.valueOf(IdWorker.nextId()));
        map.put("payment_method",createOrderDto.getPayment_method());
        map.put("place_order_time",new Date());
        map.put("erp_po",createOrderDto.getErp_po());
        map.put("receiver",createOrderDto.getReceiver());
        map.put("phone",createOrderDto.getPhone());
        map.put("postal",createOrderDto.getPostal());
        map.put("address",createOrderDto.getAddress());
        map.put("freight",0);
        //商品含税总额
        BigDecimal totalAmount = createOrderDto.getCartIds().stream().map(m -> m.getPrice().multiply(m.getGoods_num())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);
        //税额
        BigDecimal taxAmount = createOrderDto.getCartIds().stream().map(t -> t.getPrice().subtract(t.getPretax_price()).multiply(t.getGoods_num())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);
        map.put("pretax_total",totalAmount.subtract(taxAmount));
        map.put("total",totalAmount);
        map.put("amount",totalAmount);
        map.put("place_order_user_id",PmUtil.userFormat());
        map.put("place_order_fullname",RequestContext.getLoginRealName());
        SelectorFormat currentDepartment = boValidatedAndFormatService.getCurrentDepartment();
        map.put("organization_id", currentDepartment);
        map.put("enabled", true);
        map.put("type", OrderTypeEnum.ShopOrder.getCode());
        map.put("pretax_freight",0);
        map.put("pretax_amount",totalAmount);
        map.put("tax_payable",taxAmount);
        map.put("accept_delivery_time",createOrderDto.getAccept_delivery_time());
        map.put("order_customer_status", OrderCustomerStatusEnum.UpcomingConfirm.getCode());
        map.put("actual_order",RequestContext.getLoginRealName());
        map.put("tax_payable_freight",0);
        map.put("deleted",false);
        return map;
    }

    //初始化供应商订单
    private Map<String,Object> initSupplierOrder(CreateOrderDto createOrderDto,Map<String,Object> customerOrder,List<GoodsMaterialDto> goodsMaterialDtoList){
        Map<String, Object> map = Maps.newHashMap();
        map.put("id",String.valueOf(IdWorker.nextId()));
        map.put("order_customer_id",customerOrder.get("id"));
        map.put("freight",0);
        map.put("pretax_total",goodsMaterialDtoList.stream().map(t->t.getPretax_price().multiply(t.getGoods_num())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).setScale(2,BigDecimal.ROUND_HALF_UP));
        map.put("total",goodsMaterialDtoList.stream().map(GoodsMaterialDto::getAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).setScale(2,BigDecimal.ROUND_HALF_UP));
        map.put("amount",map.get("total"));
        map.put("place_order_time",customerOrder.get("place_order_time"));
        String id = CollectionUtils.firstElement(goodsMaterialDtoList).getVendor_id();
        map.put("organization_id", PmUtil.orgFormat(id));
        Map organization = BoServiceUtils.loadByBizObjectId(ApplicationConf.ORGANIZATION,id).getData().getData();
        map.put("organization_name",organization.get("name"));
        map.put("memo",createOrderDto.getMemo());
        map.put("after_sale",AfterSaleStatusEnum.NOT_AFTER_SALE.getDesc());
        map.put("pretax_freight",0);
        map.put("pretax_amount",map.get("pretax_total"));
        map.put("tax_payable",((BigDecimal)map.get("total")).subtract((BigDecimal)map.get("pretax_total")));
        map.put("order_vendor_status",OrderVendorStatusEnum.UpcomingConfirm.getCode());
        map.put("erp_po",createOrderDto.getErp_po());
        map.put("tax_payable_freight",0);
        map.put("receiver",customerOrder.get("receiver"));
        map.put("phone",0);
        map.put("postal",customerOrder.get("postal"));
        map.put("address",customerOrder.get("address"));
        map.put("deleted",false);
        map.put("actual_order",RequestContext.getLoginRealName());
        map.put("source","ShopOrder");
        return map;
    }

    //初始化客户订单商品
    private Map<String,Object> initCustomerOrderGoods(GoodsMaterialDto goodsMaterialDto,Map<String,Object> customerOrder,Map<String,Object> supplierOrder,Map<String,Object> goods,Map<String,Object> supplierOrderGoods){
        Map<String, Object> map = Maps.newHashMap();
        map.put("id",String.valueOf(IdWorker.nextId()));
        map.put("order_customer_id",customerOrder.get("id"));
        map.put("order_vendor_id",supplierOrder.get("id"));
        map.put("goods_id",goods.get("id"));
        map.put("goods_src","Shop");
        map.put("place_order_time",customerOrder.get("place_order_time"));
        map.put("category",goods.get("catalog"));
        map.put("brand",goods.get("brand"));
        map.put("name",goods.get("name"));
        map.put("model",goods.get("model"));
        map.put("spec",goods.get("spec"));
        map.put("sku",goodsMaterialDto.getMaterial_no());
        map.put("bar_code",goods.get("bar_code"));
        map.put("golden_tax",goods.get("golden_tax"));
        map.put("unspsc",goods.get("unspsc"));
        map.put("images",goods.get("images"));
        map.put("technical",goods.get("technical"));
        map.put("warranty",goods.get("warranty"));
        map.put("packaging",goods.get("packaging"));
        map.put("description",goods.get("description"));
        map.put("delivery",goods.get("delivery"));
        map.put("length",PmUtil.numberFormat((BigDecimal)goods.get("length")));
        map.put("width",PmUtil.numberFormat((BigDecimal)goods.get("width")));
        map.put("height",PmUtil.numberFormat((BigDecimal)goods.get("height")));
        map.put("weight",PmUtil.numberFormat((BigDecimal)goods.get("weight")));
        map.put("package_quantity",PmUtil.numberFormat((BigDecimal)goods.get("package_num")));
        map.put("package_unit",goods.get("package_unit"));
        map.put("quantity",goodsMaterialDto.getGoods_num());
        map.put("unit",goods.get("unit"));
        map.put("tax_rate",PmUtil.numberFormat((BigDecimal)goods.get("tax_rate")));
        map.put("pretax_price",goodsMaterialDto.getPretax_price());
        map.put("price",goodsMaterialDto.getPrice());
        map.put("freight_rate",0);
        map.put("freight",0);
        map.put("pretax_total",goodsMaterialDto.getPretax_price().multiply(goodsMaterialDto.getGoods_num()));
        map.put("tax",goodsMaterialDto.getPrice().subtract(goodsMaterialDto.getPretax_price()).multiply(goodsMaterialDto.getGoods_num()).setScale(2,BigDecimal.ROUND_HALF_UP));
        map.put("tax_freight",0);
        map.put("total",goodsMaterialDto.getPrice().multiply(goodsMaterialDto.getGoods_num()).setScale(2,BigDecimal.ROUND_HALF_UP));
        map.put("pretax_freight",0);
        map.put("pretax_amount",map.get("pretax_total"));
        map.put("amount",map.get("total"));
        map.put("customer_account_period",supplierOrderGoods.get("customer_account_period"));
        map.put("vendor_account_period",supplierOrderGoods.get("vendor_account_period"));
        map.put("memo",supplierOrder.get("memo"));
        map.put("place_order_user_id",supplierOrderGoods.get("place_order_user_id"));
        map.put("place_order_fullname",supplierOrderGoods.get("place_order_fullname"));
        map.put("customer_organization_id",supplierOrderGoods.get("customer_organization_id"));
        map.put("customer_organization_name",supplierOrderGoods.get("customer_organization_name"));
        map.put("vendor_organization_id",supplierOrderGoods.get("vendor_organization_id"));
        map.put("vendor_organization_name",supplierOrderGoods.get("vendor_organization_name"));
        map.put("quantity_shipped",0);
        map.put("quantity_received",0);
        map.put("quantity_return_not_shipped",0);
        map.put("quantity_return_shipped",0);
        map.put("returned_num",0);
        map.put("return_received_num",0);
        map.put("return_pm_received_num",0);
        map.put("receiver",customerOrder.get("receiver"));
        map.put("phone",customerOrder.get("phone"));
        map.put("address",customerOrder.get("address"));
        map.put("postal",customerOrder.get("postal"));
        map.put("erp_po",supplierOrder.get("erp_po"));
        map.put("order_customer_goods_status","UpcomingConfirm");
        map.put("quantity_unit",goods.get("unit"));
        map.put("package_quantity_unit",goods.get("package_unit"));
        map.put("undelivered_quantity",goodsMaterialDto.getGoods_num());
        map.put("signed_quantity",0);
        map.put("delivery_quantity_units",goods.get("package_unit"));
        map.put("deleted",false);
        map.put("quantity_returnable",goodsMaterialDto.getGoods_num());
        map.put("order_vendor_status","ReturnPending");
        return map;
    }



    //初始化供应商订单商品
    private Map<String,Object> initSupplierOrderGoods(GoodsMaterialDto goodsMaterialDto,CreateOrderDto createOrderDto,Map<String,Object> goods,Map<String,Object> customerOrder,Map<String,Object> supplierOrder){
        Map<String, Object> map = Maps.newHashMap();
        map.put("id",String.valueOf(IdWorker.nextId()));
        map.put("order_customer_id",customerOrder.get("id"));
        map.put("order_vendor_id",supplierOrder.get("id"));
        map.put("goods_id",goodsMaterialDto.getGoods_id());
        map.put("goods_src","Shop");
        map.put("place_order_time",customerOrder.get("place_order_time"));
        map.put("category",goods.get("catalog"));
        map.put("brand",goods.get("catalog"));
        map.put("model",goods.get("model"));
        map.put("name",goods.get("name"));
        map.put("spec",goods.get("spec"));
        map.put("sku",goodsMaterialDto.getMaterial_no());
        map.put("bar_code",goods.get("bar_code"));
        map.put("golden_tax",goods.get("golden_tax"));
        map.put("unspsc",goods.get("unspsc"));
        map.put("images",goods.get("images"));
        map.put("technical",goods.get("technical"));
        map.put("warranty",goods.get("warranty"));
        map.put("packaging",goods.get("packaging"));
        map.put("description",goods.get("description"));
        map.put("delivery",goods.get("delivery"));
        map.put("length",PmUtil.numberFormat((BigDecimal) goods.get("length")));
        map.put("width",PmUtil.numberFormat((BigDecimal) goods.get("width")));
        map.put("weight",PmUtil.numberFormat((BigDecimal)goods.get("weight")));
        map.put("height",PmUtil.numberFormat((BigDecimal)goods.get("height")));
        map.put("package_quantity",PmUtil.numberFormat((BigDecimal)goods.get("package_num")));
        map.put("package_unit",goods.get("package_unit"));
        map.put("quantity",goodsMaterialDto.getGoods_num());
        map.put("unit",goods.get("unit"));
        map.put("tax_rate",PmUtil.numberFormat((BigDecimal)goods.get("tax_rate")));
        map.put("pretax_price",goodsMaterialDto.getPretax_price());
        map.put("price",goodsMaterialDto.getPrice());
        map.put("freight_rate",0);
        map.put("freight",0);
        map.put("pretax_total",goodsMaterialDto.getPretax_price().multiply(goodsMaterialDto.getGoods_num()).setScale(2,BigDecimal.ROUND_HALF_UP));
        map.put("tax",goodsMaterialDto.getPrice().subtract(goodsMaterialDto.getPretax_price()).multiply(goodsMaterialDto.getGoods_num()).setScale(2,BigDecimal.ROUND_HALF_UP));
        map.put("tax_freight",0);
        map.put("total",goodsMaterialDto.getPrice().multiply(goodsMaterialDto.getGoods_num().setScale(2,BigDecimal.ROUND_HALF_UP)));
        map.put("pretax_freight",0);
        map.put("pretax_amount",map.get("pretax_total"));
        map.put("amount",map.get("total"));
        Map<String, Object> vendor = BoServiceUtils.loadByBizObjectId(ApplicationConf.ORGANIZATION, (String) goods.get("vendor_id")).getData().getData();
        map.put("vendor_account_period", vendor.get("statement_cycle"));
        OrgVo orgRootOrganization = PmUtil.getOrgOrganization("");
        map.put("customer_account_period",orgRootOrganization.getStatement_cycle());
        map.put("place_order_user_id",PmUtil.userFormat());
        map.put("place_order_fullname",RequestContext.getLoginRealName());
        map.put("customer_organization_id", PmUtil.orgFormat(orgRootOrganization.getId()));
        map.put("customer_organization_name",orgRootOrganization.getName());
        map.put("vendor_organization_id",PmUtil.orgFormat((String)goods.get("vendor_id")));
        map.put("vendor_organization_name",vendor.get("name"));
        map.put("quantity_shipped",0);
        map.put("quantity_received",0);
        map.put("quantity_return_not_shipped",0);
        map.put("quantity_return_shipped",0);
        map.put("quantity_unit",goods.get("unit"));
        map.put("package_quantity_unit",goods.get("package_unit"));
        map.put("erp_po",createOrderDto.getErp_po());
        map.put("deleted",false);
        map.put("order_vendor_status","UpcomingConfirm");
        map.put("order_vendor_goods_status","UpcomingConfirm");
        map.put("type","ShopOrder");
        map.put("full_name",goods.get("name"));
        map.put("order_goods_returns_status","ReturnPending");
        map.put("refunded_num",goodsMaterialDto.getGoods_num());
        map.put("deliverable_num",goodsMaterialDto.getGoods_num());
        return map;
    }

    //初始化购物车
    private Map<String, Object> initCart(MarketGoodsVo goods, AddCartDto addCartDto){
        Map<String, Object> map = Maps.newHashMap();
        map.put("id",IdWorker.nextId());
        map.put("type", CartTypeEnum.SHOP.getId());
        map.put("goods_src", GoodsSrcEnum.SHOP.getCode());
        map.put("goods_id",goods.getId());
        map.put("brand",goods.getBrand());
        map.put("name",goods.getName());
        map.put("model",goods.getModel());
        map.put("spec",goods.getSpec());
        map.put("images",goods.getImages());
        map.put("unit",goods.getUnit());
        map.put("quantity",addCartDto.getGoods_number());
        map.put("package_unit",goods.getPackage_unit());
        map.put("package_quantity",goods.getPackage_num());
        map.put("warranty",goods.getWarranty());
        map.put("delivery", goods.getDelivery());
        map.put("tax_rate",goods.getTax_rate());
        map.put("price",goods.getPrice());
        map.put("freight",0);
        map.put("total",addCartDto.getAmount());
        map.put("amount",addCartDto.getAmount());
        map.put("enabled",addCartDto.getFlag());
        map.put("min_order",goods.getMin_order());
        OrgVo organization = PmUtil.getOrgOrganization("");
        map.put("customer_organization_id", PmUtil.orgFormat(organization.getId()));
        map.put("customer_organization_name",organization.getName());
        map.put("vendor_organization_id",CollectionUtils.firstElement(goods.getVendor_id()));
        map.put("vendor_organization_name",CollectionUtils.firstElement(goods.getVendor_id()).getName());
        map.put("member_id",PmUtil.userFormat());
        map.put("deleted",false);
        map.put("pretax_price",addCartDto.getPretax_price());
        map.put("pretax_total",addCartDto.getPretax_price().multiply(BigDecimal.valueOf(addCartDto.getGoods_number())));
        map.put("tax_payable",0);
        map.put("pretax_freight",0);
        map.put("tax_rate_freight",0);
        map.put("tax_payable_freight",0);
        map.put("pretax_freight_total",0);
        map.put("freight_total",0);
        map.put("tax_payable_freight_tota",0);
        map.put("pretax_amount",map.get("pretax_total"));
        return map;
    }

    //商品校验
    private void checkGoods(Map<String, GoodsMaterialDto> materialDtoMap, List<String> ids, List<Map<String, Object>> data) {
        List<String> resIds = data.stream().map(m -> (String) m.get("id")).collect(Collectors.toList());
        ids.removeAll(resIds);
        if(!CollectionUtils.isEmpty(ids)){
            throw new BizException("商品序列号:".concat(String.join(",",ids)).concat("不可用"));
        }
        data.forEach(bo->{
            Assert.isTrue(1==(Integer)bo.get("saled"),"商品已下架");
            Assert.isTrue(1==(Integer)bo.get("enabled"),"商品已不可采购");
            Assert.isTrue(3==Integer.parseInt((String)bo.get("review_status")),"商品已不可采购");
            Assert.isTrue(BoUtils.dateFormat((String)bo.get("expiry")).getTime()>=System.currentTimeMillis(),"商品已过期");
            BigDecimal stock = (BigDecimal) bo.get("stock");
            //允许超卖,库存为0，有无库存交货期的，可以下单
            if(materialDtoMap.get((String)bo.get("id")).getGoods_num().compareTo(stock)>0 && StringUtils.isEmpty(bo.get("delivery")))
                throw  new BizException("库存不足");
        });
    }

    //订单初始化
    private void buildOrder(Integer count,CreateOrderDto createOrderDto, Map<String, GoodsMaterialDto> materialDtoMap, Map<String, List<GoodsMaterialDto>> vendorGoodsMaterialDtoMap, Map<String, Object> customerOrder, List<Map<String, Object>> supplierOrderList, List<Map<String, Object>> supplierOrderGoodsList, List<Map<String, Object>> customerOrderGoodsList) {
        if(count>5){
            throw new BizException("下单失败，请重试");
        }
        for(String k : vendorGoodsMaterialDtoMap.keySet()){
            List<GoodsMaterialDto> v = vendorGoodsMaterialDtoMap.get(k);
            //初始化供应商订单
            Map<String, Object> supplierOrder = initSupplierOrder(createOrderDto, customerOrder,v);
            supplierOrderList.add(supplierOrder);
            List<String> ids = v.stream().map(GoodsMaterialDto::getGoods_id).collect(Collectors.toList());
            SingleResponse<BOList> response = BoServiceUtils.findListBySimple(ApplicationConf.GOODES, "id", ids, Operator.IN);
            List<Map<String, Object>> data = response.getData().getData();
            if(!CollectionUtils.isEmpty(data)){
                checkGoods(materialDtoMap, ids, data);
            }else {
                throw new BizException("商品不可用");
            }
            Map<Object, Map<String, Object>> goodsIdMap = data.stream().map(t->{
                t.put("vendor_id", JSON.parseObject(JSON.toJSONString((CollectionUtils.firstElement((List)t.get("vendor_id")))), SelectorFormat.class).getId());
                return t;
            }).collect(Collectors.toMap(goods -> goods.get("id"), Function.identity()));
            for (GoodsMaterialDto g:v) {
                Map<String, Object> goodsMap = goodsIdMap.get(g.getGoods_id());
                //初始化供应商订单商品
                Map<String, Object> supplierOrderGoods = initSupplierOrderGoods(g, createOrderDto, goodsMap, customerOrder, supplierOrder);
                supplierOrderGoodsList.add(supplierOrderGoods);
                //初始化客户订单商品
                Map<String, Object> customerOrderGoods = initCustomerOrderGoods(g, customerOrder, supplierOrder, goodsMap, supplierOrderGoods);
                customerOrderGoodsList.add(customerOrderGoods);

                String sql;
                if(!StringUtils.isEmpty(goodsMap.get("delivery"))){
                    //如果有无库存交货期的话,就按照无限库存处理.
                    sql = "update "+COMMODITYMATERIALS_GOODES+" set stock = stock-? where id = ?";
                }else {
                    sql = "update "+COMMODITYMATERIALS_GOODES+" set stock = stock-?,version = version+1 where id = ? and version = ".concat(goodsMap.get("version").toString());
                }
                int num = jdbcTemplate.update(sql, g.getGoods_num(), g.getGoods_id());
                if(num<1){
                    log.warn("库存扣减失败,第"+count+"次");
                    this.buildOrder(count++, createOrderDto, materialDtoMap,  vendorGoodsMaterialDtoMap, customerOrder,  supplierOrderList,  supplierOrderGoodsList,  customerOrderGoodsList);
                }
                String querySql = "select stock from "+COMMODITYMATERIALS_GOODES+" where id = ".concat("'").concat(g.getGoods_id()).concat("'");
                BigDecimal stock = jdbcTemplate.queryForObject(querySql, (rs, rowNum) ->
                        rs.getBigDecimal("stock")
                );
                //判断是否低于安全库存，发送邮件
                if(Objects.nonNull(goodsMap.get("safe_stock"))&&Optional.ofNullable(stock).orElse(BigDecimal.ZERO).compareTo((BigDecimal) goodsMap.get("safe_stock"))>0) {
                    OrgVo organization = PmUtil.getOrgOrganization("");
                    MailTask mailTask = MailTask.builder()
                            .goodsId(g.getGoods_id())
                            .receiveMailAccount(organization.getEmail())
                            .receiveName(organization.getName())
                            .url(String.format(PmUtil.getProjectUrl().concat(ApplicationConf.goods_detail_url),g.getGoods_id()))
                            .build();
                    executor.submit(mailTask);
                    //SendMailTask.add(mailTask);
                }
            }
        }
    }
}
